/*
 * Copyright (c) 2025 Huawei Device, Inc. Ltd. and <马弓手>.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


#include "BaiduMapLocation.h"
#include "cJSON.h"
#include "translateWgs.h"

string BaiduMapLocation::coolType_bd09ll = "bd09ll";
string BaiduMapLocation::coolType_gcj02 = "gcj02";
string BaiduMapLocation::coolType_wgs84 = "wgs84";

REGISTER_PLUGIN_CLASS(BaiduMapLocation)
bool BaiduMapLocation::execute(const string&  action, cJSON* args, CallbackContext cbc) 
{
    if(action == "getCurrentPosition") {
        m_cbc = cbc;
        m_strCoolType = coolType_bd09ll;
        getLocation(cbc);
    }
    if(action == "onArKTsResult") {
        return onArKTsResult(args);
    }
    return true;
}

void BaiduMapLocation::getLocation(CallbackContext cbc)
{
    executeArkTs("./LocationAction/LocationAction/GetCurrentPosition", 0, "", "BaiduMapLocation", cbc);
}

bool BaiduMapLocation::onArKTsResult(cJSON* args)
{
    cJSON* json = cJSON_GetObjectItem(args, "result");
    if(json != NULL && json->type == cJSON_Array) {
        int count = cJSON_GetArraySize(json);
        if(count > 0) {
            string result = cJSON_GetArrayItem(json,0)->valuestring;
            
            if(result == "OK") {
                string addr = cJSON_GetArrayItem(json,1)->valuestring;
                
                cJSON* content = cJSON_GetObjectItem(args, "content");
                
                cJSON* pContent = cJSON_Parse(content->valuestring);
                
                int sourceType = 0;
                cJSON* pSourceType = cJSON_GetObjectItem(pContent, "sourceType");
                if(pSourceType != nullptr && pSourceType->type == cJSON_Number) {
                    sourceType = pSourceType->valueint;
                }
                
                string strSourceType = "";
                if(sourceType == 1) {
                    strSourceType = "GNSS";
                } else if(sourceType == 2) {
                    strSourceType = "NETWORK";
                } else if(sourceType == 3) {
                    strSourceType = "INDOOR";
                } else if(sourceType == 4) {
                    strSourceType = "RTK";
                }
                double latitude = 0.0;
                cJSON* pLatitude = cJSON_GetObjectItem(pContent, "latitude");
                if(pLatitude != NULL) {
                    latitude = pLatitude->valuedouble;
                }
                
                double longitude = 0.0;    
                cJSON* pLongitude = cJSON_GetObjectItem(pContent, "longitude");  
                if(pLongitude != NULL) {
                    longitude = pLongitude->valuedouble;
                }
                
                double altitude = 0.0;    
                cJSON* pAltitude = cJSON_GetObjectItem(pContent, "altitude");  
                if(pAltitude != NULL) {
                    altitude = pAltitude->valuedouble;
                } 
                    
                double accuracy = 0.0;    
                cJSON* pAccuracy = cJSON_GetObjectItem(pContent, "accuracy");  
                if(pAccuracy != NULL) {
                    accuracy = pAccuracy->valuedouble;
                }
                    
                double speed = 0.0;    
                cJSON* pSpeed = cJSON_GetObjectItem(pContent, "speed");  
                if(pSpeed != NULL) {
                    speed = pSpeed->valuedouble;
                }     
                
                double timeStamp = 0.0;    
                cJSON* pTimeStamp = cJSON_GetObjectItem(pContent, "timeStamp");  
                if(pTimeStamp != NULL) {
                    timeStamp = pTimeStamp->valuedouble;
                }    
                    
                double direction = 0.0;    
                cJSON* pDirection = cJSON_GetObjectItem(pContent, "direction");  
                if(pDirection != NULL) {
                    direction = pDirection->valuedouble;
                }
                
                double timeSinceBoot = 0.0;    
                cJSON* pTimeSinceBoot = cJSON_GetObjectItem(pContent, "timeSinceBoot");  
                if(pTimeSinceBoot != NULL) {
                    timeSinceBoot = pTimeSinceBoot->valuedouble;
                }
                
                double altitudeAccuracy = 0.0;    
                cJSON* pAltitudeAccuracy = cJSON_GetObjectItem(pContent, "altitudeAccuracy");  
                if(pAltitudeAccuracy != NULL) {
                    altitudeAccuracy = pAltitudeAccuracy->valuedouble;
                }
                    
                cJSON* extra = cJSON_Parse(addr.c_str());
                
                string strCountryCode = "";
                cJSON* pCountryCode = cJSON_GetObjectItem(extra, "countryCode");
                if(pCountryCode != nullptr && pCountryCode->type == cJSON_String) {
                    strCountryCode = pCountryCode->valuestring;
                }
                
                string strCountryName = "";
                cJSON* pCountryName = cJSON_GetObjectItem(extra, "countryName");
                if(pCountryName != nullptr && pCountryName->type == cJSON_String) {
                    strCountryName = pCountryName->valuestring;
                }
                string strCityCode = "";
                string strAdminCode = "";
                cJSON* pDescriptions = cJSON_GetObjectItem(extra, "descriptions");
                if(pDescriptions != nullptr && pDescriptions->type == cJSON_Array) {
                    int nCount = cJSON_GetArraySize(pDescriptions);
                    if(nCount > 0) {
                        strCityCode = cJSON_GetArrayItem(pDescriptions, 0)->valuestring;
                    }
                    if(nCount > 1) {
                        strAdminCode = cJSON_GetArrayItem(pDescriptions, 1)->valuestring;
                    }
                }
                
                string strSubAdministrativeArea = "";
                cJSON* pSubAdministrativeArea = cJSON_GetObjectItem(extra, "subAdministrativeArea");
                if(pSubAdministrativeArea != nullptr && pSubAdministrativeArea->type == cJSON_String) {
                    strSubAdministrativeArea = pSubAdministrativeArea->valuestring;
                }
                
                string strSubLocality = "";
                cJSON* pSubLocality = cJSON_GetObjectItem(extra, "subLocality");
                if(pSubLocality != nullptr && pSubLocality->type == cJSON_String) {
                    strSubLocality = pSubLocality->valuestring;
                }
                
                string strRoadName = "";
                cJSON* pRoadName = cJSON_GetObjectItem(extra, "roadName");
                if(pRoadName != nullptr && pRoadName->type == cJSON_String) {
                    strRoadName = pRoadName->valuestring;
                }
                
                string strPlaceName = "";
                cJSON* pPlaceName = cJSON_GetObjectItem(extra, "placeName");
                if(pPlaceName != nullptr && pPlaceName->type == cJSON_String) {
                    strPlaceName = pPlaceName->valuestring;
                }
                
                string strAdministrativeArea = "";
                cJSON* pAdministrativeArea = cJSON_GetObjectItem(extra, "administrativeArea");
                if(pAdministrativeArea != nullptr && pAdministrativeArea->type == cJSON_String) {
                    strAdministrativeArea = pAdministrativeArea->valuestring;
                }
                
                string strPremises = "";
                cJSON* pPremises = cJSON_GetObjectItem(extra, "premises");
                if(pPremises != nullptr && pPremises->type == cJSON_String) {
                    strPremises = pPremises->valuestring;
                }
                
                string strLocale = "";
                cJSON* pLocale = cJSON_GetObjectItem(extra, "locale");
                if(pLocale != nullptr && pLocale->type == cJSON_String) {
                    strLocale = pLocale->valuestring;
                }
                
               
                if(m_strCoolType == coolType_gcj02) {
                    translateWgs::wgs84ToGcj02(latitude, longitude, latitude, longitude);
                }
                if(m_strCoolType == coolType_bd09ll) {
                    translateWgs::wgs84ToGcj02(latitude, longitude, latitude, longitude);
                    translateWgs::gcj02toBd09(longitude, latitude, longitude, latitude);
                }    
                    
                cJSON*  coords = cJSON_CreateObject(); 
                cJSON_AddNumberToObject(coords, "time", timeStamp);
                cJSON_AddNumberToObject(coords, "locType", sourceType);
                cJSON_AddStringToObject(coords, "locTypeDescription", strSourceType.c_str());
                cJSON_AddNumberToObject(coords, "latitude", latitude);
                cJSON_AddNumberToObject(coords, "longitude", longitude);
                cJSON_AddNumberToObject(coords, "altitude", altitude);
                cJSON_AddNumberToObject(coords, "radius", accuracy);//精度
                cJSON_AddStringToObject(coords, "countryCode", strCountryCode.c_str());
                cJSON_AddStringToObject(coords, "country", strCountryName.c_str());
                cJSON_AddStringToObject(coords, "citycode", strCityCode.c_str());
                cJSON_AddStringToObject(coords, "city", strSubAdministrativeArea.c_str());
                cJSON_AddStringToObject(coords, "district", strSubLocality.c_str());
                cJSON_AddStringToObject(coords, "street", strRoadName.c_str());
                cJSON_AddStringToObject(coords, "addr", strPlaceName.c_str());
                cJSON_AddStringToObject(coords, "province", strAdministrativeArea.c_str());
                cJSON_AddStringToObject(coords, "userIndoorState", strPremises.c_str());
                cJSON_AddNumberToObject(coords, "direction", direction);
                cJSON_AddStringToObject(coords, "locationDescribe", strLocale.c_str());
                
                m_cbc.success(coords);
                cJSON_Delete(coords);
            } else {
                cJSON*  coords = cJSON_CreateObject(); 
                cJSON_AddStringToObject(coords, "describe", "定位失败");
                m_cbc.error(coords);
                cJSON_Delete(coords);
            }
        }
    }
    return true;
}